package com.chapter.sample.answer.multiplex;

import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.threadpool.TtlExecutors;
import com.chapter.sample.juc.CompletableFutureDemo;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@Slf4j
public class ThreadLocalDemo3 {
    public static void main(String[] args) throws InterruptedException {
        //m1();
        //m2();
        //m3();//InheritableThreadLocal
        //m4();
        m5();//TransmittableThreadLocal
    }

    /**
     * 解决线程池中线程因为复用二不能取得外部线程数据的问题
     * @throws InterruptedException
     */
    private static void m5() throws InterruptedException {
        TransmittableThreadLocal<String> transmittableThreadLocal = new TransmittableThreadLocal<>();
        //为了看到效果，这里创建大小为1的线程池方便看到效果，池中只有1个线程才有效果，池中只有一个线程才能看到效果
        ExecutorService threadPool = Executors.newFixedThreadPool(1);
        threadPool = TtlExecutors.getTtlExecutorService(threadPool);

        //这里是主线程，使用TransmittableThreadLocal.set放入值：java
        transmittableThreadLocal.set(Thread.currentThread().getName() + "-java");
        log.info("major：「{}」", transmittableThreadLocal.get());

        threadPool.execute(() -> {
            log.info("ThreadPool第一次获取，major：「{}」", transmittableThreadLocal.get());
        });

        TimeUnit.SECONDS.sleep(1);
        System.out.println();
        System.out.println();

        //这里又在主线程中放入 vue
        transmittableThreadLocal.set(Thread.currentThread().getName() + "-Vue");
        log.info("major：「{}」", transmittableThreadLocal.get());

        //这里又在线程池中通过transmittableThreadLocal.get()方法拿值，看看能否拿到刚刚放入的 Vue
        threadPool.execute(() -> {
            //在线程池汇中通过transmittableThreadLocal.get()，拿值，看看拿到的是啥？
            log.info("ThreadPool第2次获取，major：「{}」", transmittableThreadLocal.get());
        });
        System.out.println();

        TimeUnit.SECONDS.sleep(1);
        threadPool.shutdown();

    }

    /**
     * new 新建可以使用
     * 复用不好使，没有new
     *
     * @throws InterruptedException
     */
    private static void m4() throws InterruptedException {
        InheritableThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>();
        //这里是主线程，使用InheritableThreadLocal.set放入java
        inheritableThreadLocal.set(Thread.currentThread().getName() + "-java");
        log.info("major：{}", inheritableThreadLocal.get());

        //为了看效果，这里创建大小为1的线程池方便看效果，池中只有1个线程才有效果，池中只有1个线程才有效果
        ExecutorService threadPool = Executors.newFixedThreadPool(1);
        //在线程池中通过使用InheritableThreadLocal拿值，看看是否能拿到刚刚放入的java？
        threadPool.execute(() -> {
            log.info("threadPool第一次获取 major：{}", inheritableThreadLocal.get());
        });

        TimeUnit.SECONDS.sleep(1);
        System.out.println();
        System.out.println();

        //这里又在主线程放入了Vue
        inheritableThreadLocal.set(Thread.currentThread().getName() + "-Vue我已经修改了值");
        log.info("major：{}", inheritableThreadLocal.get());

        //在线程池中通过使用InheritableThreadLocal拿值，看看是否能拿到刚刚放入的Vue？
        threadPool.execute(() -> {
            //在线程池中拿值看看那是否能拿得到
            log.info("threadPool第一次获取 major：{}", inheritableThreadLocal.get());
        });

    }

    private static void m3() {
        InheritableThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal<>();

        inheritableThreadLocal.set(Thread.currentThread().getName() + "-java");
        log.info("major：{}", inheritableThreadLocal.get());

        new Thread(() -> {
            log.info("major：{}", inheritableThreadLocal.get());
        }, "thead-1").start();

        new Thread(() -> {
            log.info("major：{}", inheritableThreadLocal.get());
        }, "thead-2").start();

        new Thread(() -> {
            log.info("major：{}", inheritableThreadLocal.get());
        }, "thead-3").start();

    }

    private static void m2() {
        ThreadLocal<String> threadLocal = ThreadLocal.withInitial(() -> null);
        threadLocal.set(Thread.currentThread().getName() + "-java");
        log.info("major：「{}」", threadLocal.get());
        System.out.println();

        //新建线程thread1，设置vue,然后取出学科看看？
        new Thread(() -> {
            log.info("major:{}", threadLocal.get());//thread-1 是否可以取得main线程上一步写入的值？
        }, "thread-1").start();
    }

    private static void m1() throws InterruptedException {

        //ThreadLocal可以在当前线程中共享数据，set/get需要在同一个线程中执行才行，别人的取不到
        ThreadLocal<String> threadLocal = ThreadLocal.withInitial(() -> null);

        threadLocal.set(Thread.currentThread().getName() + "-java");
        log.info("major：「{}」", threadLocal.get());
        System.out.println();

        //新建线程thread1，设置vue,然后取出学科看看？
        new Thread(() -> {
            log.info("major:{}", threadLocal.get());//thread-1 是否可以取得main线程上一步写入的值？
            threadLocal.set(Thread.currentThread().getName() + "-Vue");
            log.info("major:{}", threadLocal.get());
        }, "thread-1").start();

        //新建线程thread1，设置Flink,然后取出学科看看？
        new Thread(() -> {
            log.info("major:{}", threadLocal.get());
            threadLocal.set(Thread.currentThread().getName() + "-Flink");
            log.info("major:{}", threadLocal.get());
        }, "thread-2").start();

        CompletableFuture.supplyAsync(() -> {
            log.info("major:{}", threadLocal.get());
            threadLocal.set(Thread.currentThread().getName() + "-MySQL");
            log.info("major:{}", threadLocal.get());
            return null;
        });
        TimeUnit.SECONDS.sleep(1);
    }
}
